import math

import pandas as pd
from math import radians, cos, sin, asin, sqrt,pi
import numpy as np
import scipy

# 一种设置为指定范围index的方法：
# 在df最后concat一列，值为指定范围的数，然后使用set_index(shape[1])设置索引为这一列就行
#df=df.reset_index(drop=True)，必须加上drop=True才能使索引从0开始并且原来的df不会被删除或者置为NaN
#对df使用apply，第一个参数是要使用的函数，最好指定axis，比如axis==1，对一行应用函数,那么df的每一行都会作为函数的第一个参数传递进去
# CO:4 O3:160 NO2:80 SO2:50  NOx:不管(1000) NO:50  TVOC:1000  O38H:1000
#只检测SO2 NO2 O3 CO
class SceneJudge:
    initData=pd.DataFrame()#接受excel读进来的数据
    standardArr=[]#存放了每种气体的超标阈值
    title=pd.DataFrame()#存放表的标题
    contaminated=pd.DataFrame()#存放污染区域的df
    def __init__(self,file,list):
        fileDf=pd.read_excel(file,header=None)#header=None代表不适用表中第一行作为df的columns
        self.initData=fileDf.copy(deep=True)
        self.standardArr=list
        self.title=fileDf.loc[0]

    #找出表中的所有污染点
    def findPolution(self)->pd.DataFrame:
        df=self.initData.copy(deep=True)
        df=df.drop(axis=1,index=0)#要删除第一行，因为第一行是str，不能与int作比较，删除后的df索引任然从1开始
        df=df.reset_index(drop=True)#现在索引从0开始了
        df.fillna(value=0)#原表有很多缺省值，所以填充缺省值为0
        contaminated=df.loc[(df[9]>self.standardArr[0])|(df[10]>self.standardArr[1])|(df[11]>self.standardArr[2])|(df[12]>self.standardArr[3])|(df[13]>self.standardArr[4])|(df[14]>self.standardArr[5])|(df[21]>self.standardArr[6])|(df[22]>self.standardArr[7])|(df[23]>self.standardArr[8])|(df[24]>self.standardArr[9])]
        self.contaminated=contaminated
        return contaminated

    #对外提供的接口，返回所有被污染点的详细信息
    def getContaminatedInf(self):
        contaminatedInf=self.findPolution()
        #contaminatedInf=contaminatedInf.reset_index(drop=True)#重置索引从0开始（不能重置索引，因为重置后溯源和这个不好比对）
        recordNums=contaminatedInf.shape[0]#超标记录的数目
        ansInfoMapArr=[]
        #遍历所有超标记录
        for i in range(0,recordNums):
            infMap={}
            infMap['id']=i+1#id代表这是第几条污染记录
            infMap['stationCode']=contaminatedInf.iloc[i,0]#站点编码
            infMap['stationName']=contaminatedInf.iloc[i,1]#站点名称
            infMap['equipmentType']=contaminatedInf.iloc[i,2]#设备类型
            infMap['sourceType']=contaminatedInf.iloc[i,3]#源类型
            infMap['district']=contaminatedInf.iloc[i,4]#区县
            infMap['longitude']=contaminatedInf.iloc[i,5]#经度
            infMap['dimension']=contaminatedInf.iloc[i,6]#维度
            infMap['time']=contaminatedInf.iloc[i,7]#时间
            infMap['AQI']=contaminatedInf.iloc[i,8]#AQI
            excessGas=dict()
            #查找哪些气体超标了
            for col in range(9,15):#从PM10到CO
                if contaminatedInf.iloc[i,col]>self.standardArr[col-9]:
                    gasName=self.title.tolist()[col]#超标气体名称
                    excessGas[gasName]=contaminatedInf.iloc[i,col]#key是气体名称，value是其浓度
            for ncol in range(21,25):#NOx到O38H
                if contaminatedInf.iloc[i,ncol]>self.standardArr[ncol-15]:
                    gasName=self.title.tolist()[ncol]#超标气体名称
                    excessGas[gasName]=contaminatedInf.iloc[i,ncol]#key是气体名称，value是其浓度
            infMap['excessGas']=excessGas#这条记录的所有超标气体及其对应浓度
            ansInfoMapArr.append(infMap)
        return ansInfoMapArr

    #根据经纬度计算两点距离，结果单位是米，这个函数的计算精度很高，精确到了米级别，误差很小
    def distance(self,lon1, lat1, lon2, lat2):
        lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
        c = 2 * asin(sqrt(a))
        r = 6371
        return c * r*1000

    def judgeSource(self):
        contaminated=self.findPolution()
        # contaminated.reset_index(drop=True)
        itemNum=contaminated.shape[0]#记录条数
        list=[]#用于装载每种污染气体超标的容器的容器
        SO2=pd.DataFrame()
        NO2=pd.DataFrame()
        O3=pd.DataFrame()
        CO=pd.DataFrame()
        NOx=pd.DataFrame()
        NO=pd.DataFrame()
        TVOC=pd.DataFrame()
        o38H=pd.DataFrame()
        list.append(SO2)
        list.append(NO2)
        list.append(O3)
        list.append(CO)
        list.append(NOx)
        list.append(NO)
        list.append(TVOC)
        list.append(o38H)
        #按照超标气体类别进行分组
        for i in range(0,itemNum):
            item=contaminated.iloc[i]
            for j in range(11,15):#SO2到CO
                if item[j]>self.standardArr[j-9]:
                    list[j-11]=pd.concat([list[j-11],item],axis=0,ignore_index=False)
            for k in range(21,25):
                if item[k]>self.standardArr[k-15]:
                    list[k-17]=pd.concat([list[j-17],item],axis=0,ignore_index=False)
        #对每一种超标气体的所有记录按照该种超标气体的浓度降序排序
        for i in range(0,4):
            list[i].sort_values(by=11+i,axis=0,inplace=True)
        for j in range(4,8):
            list[j].sort_values(by=17+i,axis=0,inplace=True)




if __name__ == '__main__':
    file=r'./static/partData.xlsx'
    testSceneJudge=SceneJudge(file)

